package com.cml.domain.service;

import com.alibaba.fastjson.JSONObject;
import com.cml.common.constant.MessageType;
import com.cml.common.context.ServerContext;
import com.cml.common.dto.entity.SoltMetadata;
import com.cml.domain.entity.DefaultMessage;
import com.cml.domain.entity.ServerNode;
import com.cml.infrastructure.MessageQueueManager;

import java.util.ArrayList;
import java.util.List;

/**
 * 姓名：陈茂林
 * 时间：2023/11/21 8:38
 * 描述：
 */
public class SoltReplicasManagerService extends AbsractSoltManagerService {

    private ServerNode curServerNode;

    private SoltContextManagerService soltContextManagerService;

    private List<SoltMetadata> curServernodeReplicasRelationship=new ArrayList<>();

    private ServiceInstanceManagerService serviceInstanceManagerService = new ServiceInstanceManagerService();
    public SoltReplicasManagerService(ServerContext serverContext,SoltContextManagerService soltContextManagerService) {
        super(serverContext,soltContextManagerService);
        this.curServerNode = serverContext.getServerNode();
        this.soltContextManagerService=soltContextManagerService;
    }

    @Override
    public void startSoltManagerProcess() {
        super.startSoltManagerProcess();
        try{

            if(this.curServerNode.isLeader()){
                //todo 通知所在副本节点
                synServerNodeReplicasRelationship();
            }else{
                this.waitGetCurServernodeReplicasRelationship();
                logger.info("当前节点的副本为："+this.curServernodeReplicasRelationship);
            }
        }catch (Exception e){
           throw new RuntimeException(e);
        }
    }

    private void  synServerNodeReplicasRelationship() throws Exception {
        curServernodeReplicasRelationship=new ArrayList<>();

        for (int i = 0; i < this.getSlotsAllocation().size(); i++) {
            SoltMetadata soltMetadata = this.getSlotsAllocation().get(i);
            if(this.curServerNode.getId().equals(soltMetadata.getReplicasTargetServerNode())){
                this.curServernodeReplicasRelationship.add(soltMetadata);
            }else {
                DefaultMessage message = new DefaultMessage();
                message.setDefaultMessageType(MessageType.SERVERNODE_REPLICAS_RELATIONSHIP_MESSAGE);
                String messageJson = JSONObject.toJSONString(soltMetadata);
                message.setDefaultMessage(messageJson.getBytes());
                MessageQueueManager.sendMessage(soltMetadata.getReplicasTargetServerNode(), message);
            }
        }
    }

    private void waitGetCurServernodeReplicasRelationship() throws Exception {
        curServernodeReplicasRelationship=new ArrayList<>();
        DefaultMessage defaultMessage = (DefaultMessage) MessageQueueManager.takeServerNodeReplicasRelationshipMessage();
        this.curServernodeReplicasRelationship.add(JSONObject.parseObject(defaultMessage.getDefaultMessage(),SoltMetadata.class));
        logger.info("当前节点对应副本在节点:" + this.curServernodeReplicasRelationship);
    }

    public  List<SoltMetadata> getCurServernodeReplicasRelationship(){
        return this.curServernodeReplicasRelationship;
    }


    @Override
    protected void allocateSolt() {
        logger.info("----------------开始计算solt副本槽位------------------");
        List<SoltMetadata> slotsAllocation=soltContextManagerService.getSlotsAllocation();
        List<SoltMetadata> slotsAllocationReplicas =this.getSlotsAllocation();
        List<SoltMetadata> slotsAllocationCopy = new ArrayList<>(slotsAllocation);
        int serverNodeTotalNum = slotsAllocationCopy.size() - 1;
        int startIndex = 0;
        boolean loopMaxFlag = true;
        try {

            //从两头开始互换位置，换到中间结束
            for (int i = 0; i < slotsAllocation.size(); i++) {
                if (serverNodeTotalNum == startIndex) {
                    slotsAllocationReplicas.add(slotsAllocation.get(serverNodeTotalNum).clone());
                    break;
                }
                if (loopMaxFlag) {
                    slotsAllocationReplicas.add(slotsAllocation.get(serverNodeTotalNum).clone());
                    serverNodeTotalNum--;
                    loopMaxFlag = false;
                } else {
                    slotsAllocationReplicas.add(slotsAllocation.get(startIndex).clone());
                    startIndex++;
                    loopMaxFlag = true;
                }
            }


            //重置服务节点id
            for (int i = 0; i < this.getSlotsAllocation().size(); i++) {
                SoltMetadata replicasServerNode = slotsAllocationReplicas.get(i);
                replicasServerNode.setReplicasTargetServerNode(replicasServerNode.getServerNodeId());
                replicasServerNode.setServerNodeId(i + 1);
                replicasServerNode.setReplicas(true);
            }
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
        logger.info("副本情况如下：");
        logger.info(slotsAllocationReplicas);
        logger.info("----------------结束计算solt副本槽位------------------");
    }

    @Override
    protected Integer getSoltMetadataSynType() {
        return MessageType.SOLT_METADATA_REPLICAS_MESSAGE;
    }

    @Override
    protected Integer getSendServerNodeSoltMessageType() {
        return MessageType.CUR_SERVER_NODE_SOLT_METADATA_REPLICAS_MESSAGE;
    }

    @Override
    protected void waitGetCurServerNodeSoltMeatadata() throws InterruptedException {
        DefaultMessage defaultMessage = (DefaultMessage) MessageQueueManager.takeCurServerNodeSoltMetadataReplicasMessage();
        this.setCurServerNodeSoltMetadata(JSONObject.parseObject(defaultMessage.getDefaultMessage(), SoltMetadata.class));
    }

    @Override
    protected ServiceInstanceManagerService doGetServiceInstanceManagerService() {
        return serviceInstanceManagerService;
    }
}
